import { Injectable, NotFoundException, ConflictException, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, SelectQueryBuilder, In } from 'typeorm';
import { Tag, Blog } from '@app/entities';
import { 
  CreateTagDto, 
  UpdateTagDto, 
  QueryTagsDto, 
  BatchTagActionDto,
  MergeTagsDto,
  TagStatsDto 
} from '../dto';

@Injectable()
export class TagsService {
  constructor(
    @InjectRepository(Tag)
    private readonly tagRepository: Repository<Tag>,
    @InjectRepository(Blog)
    private readonly blogRepository: Repository<Blog>,
  ) {}

  async findAll(query: QueryTagsDto) {
    const queryBuilder = this.createBaseQuery();
    
    // 搜索条件
    if (query.search) {
      queryBuilder.andWhere(
        '(tag.name LIKE :search OR tag.description LIKE :search)',
        { search: `%${query.search}%` }
      );
    }

    // 状态筛选
    if (query.status !== undefined) {
      queryBuilder.andWhere('tag.status = :status', { status: query.status });
    }

    // 使用次数筛选
    if (query.minCount !== undefined) {
      queryBuilder.andWhere('tag.count >= :minCount', { minCount: query.minCount });
    }

    if (query.maxCount !== undefined) {
      queryBuilder.andWhere('tag.count <= :maxCount', { maxCount: query.maxCount });
    }

    // 排序
    const sortBy = query.sortBy || 'count';
    const sortOrder = query.sortOrder || 'DESC';
    queryBuilder.orderBy(`tag.${sortBy}`, sortOrder);

    // 分页
    const page = query.page || 1;
    const limit = query.limit || 20;
    const skip = (page - 1) * limit;

    queryBuilder.skip(skip).take(limit);

    const [tags, total] = await queryBuilder.getManyAndCount();

    return {
      tags: tags.map(tag => this.formatTagResponse(tag)),
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  async findPopular(limit: number = 10) {
    const tags = await this.tagRepository.find({
      where: { status: 1 },
      order: { count: 'DESC' },
      take: limit,
    });

    return {
      tags: tags.map(tag => this.formatTagResponse(tag)),
    };
  }

  async findOne(id: number): Promise<Tag> {
    const tag = await this.tagRepository.findOne({
      where: { id },
      relations: ['blogs'],
    });

    if (!tag) {
      throw new NotFoundException('标签不存在');
    }

    return tag;
  }

  async create(createTagDto: CreateTagDto): Promise<Tag> {
    // 检查标签名是否已存在
    const existingTag = await this.tagRepository.findOne({
      where: { name: createTagDto.name },
    });

    if (existingTag) {
      throw new ConflictException('标签名已存在');
    }

    // 生成 slug（如果没有提供）
    if (!createTagDto.slug) {
      createTagDto.slug = this.generateSlug(createTagDto.name);
    }

    const tag = this.tagRepository.create(createTagDto);
    return await this.tagRepository.save(tag);
  }

  async update(id: number, updateTagDto: UpdateTagDto): Promise<Tag> {
    const tag = await this.findOne(id);

    // 如果更新标签名，检查是否冲突
    if (updateTagDto.name && updateTagDto.name !== tag.name) {
      const existingTag = await this.tagRepository.findOne({
        where: { name: updateTagDto.name },
      });

      if (existingTag && existingTag.id !== id) {
        throw new ConflictException('标签名已存在');
      }
    }

    // 更新 slug
    if (updateTagDto.name && !updateTagDto.slug) {
      updateTagDto.slug = this.generateSlug(updateTagDto.name);
    }

    Object.assign(tag, updateTagDto);
    return await this.tagRepository.save(tag);
  }

  async remove(id: number): Promise<void> {
    const tag = await this.findOne(id);
    
    // 检查是否有博客使用此标签
    const blogCount = await this.blogRepository
      .createQueryBuilder('blog')
      .innerJoin('blog.tags', 'tag')
      .where('tag.id = :tagId', { tagId: id })
      .getCount();

    if (blogCount > 0) {
      throw new BadRequestException(`此标签被 ${blogCount} 篇博客使用，无法删除`);
    }

    await this.tagRepository.remove(tag);
  }

  async batchAction(batchActionDto: BatchTagActionDto): Promise<any> {
    const { tagIds, action } = batchActionDto;
    
    switch (action) {
      case 'activate':
        await this.tagRepository.update(tagIds, { status: 1 });
        break;
      case 'deactivate':
        await this.tagRepository.update(tagIds, { status: 0 });
        break;
      case 'delete':
        // 检查是否有博客使用这些标签
        for (const tagId of tagIds) {
          const blogCount = await this.blogRepository
            .createQueryBuilder('blog')
            .innerJoin('blog.tags', 'tag')
            .where('tag.id = :tagId', { tagId })
            .getCount();

          if (blogCount > 0) {
            const tag = await this.tagRepository.findOne({ where: { id: tagId } });
            throw new BadRequestException(`标签 "${tag?.name}" 被 ${blogCount} 篇博客使用，无法删除`);
          }
        }
        
        await this.tagRepository.delete(tagIds);
        break;
      case 'merge':
        if (batchActionDto.targetTagId) {
          await this.mergeTags(tagIds, batchActionDto.targetTagId);
        }
        break;
      default:
        throw new BadRequestException('不支持的操作类型');
    }

    return {
      processed: tagIds.length,
      action,
    };
  }

  async mergeTags(sourceTagIds: number[], targetTagId: number): Promise<any> {
    const targetTag = await this.findOne(targetTagId);
    
    // 验证源标签
    const sourceTags = await this.tagRepository.find({
      where: { id: In(sourceTagIds) },
    });

    if (sourceTags.length !== sourceTagIds.length) {
      throw new BadRequestException('部分源标签不存在');
    }

    // 检查是否包含目标标签
    if (sourceTagIds.includes(targetTagId)) {
      throw new BadRequestException('不能将标签合并到自身');
    }

    let mergedBlogsCount = 0;

    // 将源标签的博客转移到目标标签
    for (const sourceTag of sourceTags) {
      const blogs = await this.blogRepository
        .createQueryBuilder('blog')
        .innerJoinAndSelect('blog.tags', 'tag')
        .where('tag.id = :tagId', { tagId: sourceTag.id })
        .getMany();

      for (const blog of blogs) {
        // 移除源标签
        blog.tags = blog.tags.filter(tag => tag.id !== sourceTag.id);
        
        // 添加目标标签（如果还没有）
        if (!blog.tags.some(tag => tag.id === targetTagId)) {
          blog.tags.push(targetTag);
        }

        await this.blogRepository.save(blog);
        mergedBlogsCount++;
      }
    }

    // 更新目标标签计数
    await this.recalculateTagCount(targetTagId);

    // 删除源标签
    await this.tagRepository.delete(sourceTagIds);

    return {
      targetTagId,
      sourceTagIds,
      mergedBlogsCount,
    };
  }

  async getTagPosts(id: number, query: any) {
    const tag = await this.findOne(id);
    
    const queryBuilder = this.blogRepository
      .createQueryBuilder('blog')
      .innerJoin('blog.tags', 'tag')
      .leftJoinAndSelect('blog.tags', 'allTags')
      .where('tag.id = :tagId', { tagId: id });

    // 分页
    const page = query.page || 1;
    const limit = query.limit || 10;
    const skip = (page - 1) * limit;

    queryBuilder.skip(skip).take(limit);
    queryBuilder.orderBy('blog.createdAt', 'DESC');

    const [blogs, total] = await queryBuilder.getManyAndCount();

    return {
      tag: this.formatTagResponse(tag),
      blogs,
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  async getUsageStats(query: TagStatsDto): Promise<any> {
    const { type, limit } = query;
    
    let tags: Tag[] = [];
    
    switch (type) {
      case 'popular':
        tags = await this.tagRepository.find({
          where: { status: 1 },
          order: { count: 'DESC' },
          take: limit,
        });
        break;
      case 'recent':
        tags = await this.tagRepository.find({
          where: { status: 1 },
          order: { createdAt: 'DESC' },
          take: limit,
        });
        break;
      case 'usage':
      default:
        tags = await this.tagRepository.find({
          where: { status: 1 },
          order: { count: 'DESC' },
          take: limit,
        });
        break;
    }

    const totalTags = await this.tagRepository.count();
    const activeTags = await this.tagRepository.count({ where: { status: 1 } });
    const inactiveTags = await this.tagRepository.count({ where: { status: 0 } });
    const unusedTags = await this.tagRepository.count({ where: { count: 0 } });

    // 计算平均每篇博客的标签数
    const totalBlogs = await this.blogRepository.count();
    const totalTagUsage = await this.tagRepository
      .createQueryBuilder('tag')
      .select('SUM(tag.count)', 'total')
      .getRawOne();

    const averageTagsPerPost = totalBlogs > 0 ? 
      (totalTagUsage.total || 0) / totalBlogs : 0;

    return {
      totalTags,
      activeTags,
      inactiveTags,
      unusedTags,
      averageTagsPerPost: parseFloat(averageTagsPerPost.toFixed(2)),
      tags: tags.map(tag => this.formatTagResponse(tag)),
    };
  }

  private async recalculateTagCount(tagId: number): Promise<void> {
    const count = await this.blogRepository
      .createQueryBuilder('blog')
      .innerJoin('blog.tags', 'tag')
      .where('tag.id = :tagId', { tagId })
      .getCount();

    await this.tagRepository.update(tagId, { count });
  }

  private createBaseQuery(): SelectQueryBuilder<Tag> {
    return this.tagRepository.createQueryBuilder('tag');
  }

  private generateSlug(name: string): string {
    return name
      .toLowerCase()
      .replace(/[^\w\s-]/g, '')
      .replace(/\s+/g, '-')
      .trim();
  }

  private formatTagResponse(tag: Tag): any {
    return {
      ...tag,
      actualCount: tag.actualCount,
      isPopular: tag.isPopular,
      level: tag.level,
    };
  }
}
